import typing
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
import sys
from ui.Ui_net_assit_widget import Ui_Form
import socket
import threading
from utils import get_local_ip, decode_data
from datetime import datetime


class MyWidget(QWidget):
    # 定义一个信号，用于从工作线程传递数据到主线程
    data_received = QtCore.pyqtSignal(str)
    
    def __init__(self, parent=None):
        super().__init__()
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        self.tcp_socket = None
        self.init_ui()
        
        # 连接信号到槽函数
        self.data_received.connect(self.update_recv_text)
    def on_send_clicked(self):
        #判读是否已连接
        if self.tcp_socket is None:
            print("请先连接服务器")
            return
        text=self.ui.edit_send.toPlainText()
        print("发送数据:",text)
        self.tcp_socket.send(text.encode("GBK"))
    def init_ui(self):
        self.ui.btn_connect.clicked.connect(self.on_button_clicked)
        self.ui.edit_target_ip.setText("127.0.0.1")
        self.ui.edit_target_port.setText("8080")
        local_ips = get_local_ip()
        self.ui.cb_local_ip.addItems(local_ips)
        self.ui.pushButton_2.clicked.connect(self.on_send_clicked)

    def update_recv_text(self, text):
        """在主线程中更新接收文本框"""
        self.ui.edit_recv.append(text)

    @QtCore.pyqtSlot(str, str)
    def update_ui_after_connect(self, local_ip, local_port):
        """在主线程中更新UI"""
        self.ui.cb_local_ip.setCurrentIndex(self.ui.cb_local_ip.findText(local_ip))
        self.ui.edit_local_port.setText(local_port)
        self.update_connect_btn()

    def run_tcp_client(self, target_ip, target_port):
        self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.tcp_socket.connect((target_ip, int(target_port)))
            print("服务器连接成功")
            
            # 获取本地分配的端口号
            local_ip, local_port = self.tcp_socket.getsockname()
            # 使用信号更新UI，而不是直接操作
            QtCore.QMetaObject.invokeMethod(self, "update_ui_after_connect", 
                                           QtCore.Qt.QueuedConnection,
                                           QtCore.Q_ARG(str, local_ip),
                                           QtCore.Q_ARG(str, str(local_port)))
            
            while True:
                bytes_data = self.tcp_socket.recv(1024)
                if bytes_data:
                    # 在工作线程中准备数据，但通过信号发送到主线程更新UI
                    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    decoded_data = decode_data(bytes_data)
                    formatted_data = f"[{current_time}] {decoded_data}"
                    self.data_received.emit(formatted_data)
                else:
                    break
        except Exception as e:
            print("Error:", e)
        finally:
            if self.tcp_socket is not None:
                self.tcp_socket.close()
                self.tcp_socket = None
                # 使用信号更新UI
                QtCore.QMetaObject.invokeMethod(self, "update_connect_btn", 
                                               QtCore.Qt.QueuedConnection)
                print("连接已关闭")

    def on_button_clicked(self):
        if self.tcp_socket is not None:
            print("断开连接")
            self.tcp_socket.close()
            self.tcp_socket = None
            self.update_connect_btn()
            return
        
        target_ip = self.ui.edit_target_ip.text()
        target_port = self.ui.edit_target_port.text()
        print("Target IP:", target_ip)
        print("Target Port:", target_port)
        if target_ip == "" or target_port == "":
            print("请输入目标ip和端口")
            return
        
        threading.Thread(target=self.run_tcp_client, args=(target_ip, target_port), daemon=True).start()

    def update_connect_btn(self):
        """更新连接按钮文字"""
        if self.tcp_socket is not None:
            self.ui.btn_connect.setText("断开连接(已连接)")
        else:
            self.ui.btn_connect.setText("连接服务器")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWidget()
    w.show()
    sys.exit(app.exec_())